#include "../include/tlv.h"
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>

int tlv_send(int sockfd,uint32_t type,uint32_t length,const uint8_t *value){
    if(length>TLV_VALUE_MAX_SIZE){return -1;}

    uint8_t buffer[TLV_BUFFER_MAX_SIZE];
    uint32_t type_net_byte=htonl(type);
    uint32_t length_net_byte=htonl(length);
    memcpy(buffer,&type_net_byte,sizeof(type));
    memcpy(buffer+sizeof(type),&length_net_byte,sizeof(length));
    memcpy(buffer+sizeof(type)+sizeof(length),value,length);

    if(send(sockfd,buffer,sizeof(type)+sizeof(length)+length,MSG_NOSIGNAL)==-1){return -1;}

    return 0;
}

int tlv_recv(int sockfd,uint32_t *type,uint32_t *length,uint8_t *value){
    if(recv(sockfd,type,sizeof(uint32_t),MSG_WAITALL)!=sizeof(uint32_t)){return -1;}
    *type=ntohl(*type);

    if(recv(sockfd,length,sizeof(uint32_t),MSG_WAITALL)!=sizeof(uint32_t)){return -1;}
    *length=ntohl(*length);
    
    if(recv(sockfd,value,*length,MSG_WAITALL)!=*length){return -1;}

    return 0;
}

int tlv_request(int sockfd,uint32_t type,uint32_t length,const uint8_t *value,request_callback_ptr_t callback,void *arg){
    
    if(tlv_send(sockfd,type,length,value)==-1){return -1;}
    
    uint8_t buffer[TLV_VALUE_MAX_SIZE];
    if(tlv_recv(sockfd,&type,&length,buffer)==-1){return -1;}
    
    uint32_t response_code=ntohl(*(uint32_t*)buffer);
    
    if(type!=RESPONSE){return -1;}
    if(callback){ // 有回调函数时才去执行回调函数
        callback(response_code,length,buffer+sizeof(response_code),arg);
    }

    return 0;
}
